package com.shijie.utils;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * Created with Yang Huan
 * Date: 2017/3/2
 * Time: 11:34
 */
public class CommonUtil {

    private static final SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");

    public static String argumentsToString(Object... args) {
        if (args == null || args.length == 0) {
            return "";
        }

        try {
            StringBuilder buffer = new StringBuilder();
            for (int i = 0; i < args.length; i++) {
                if (args[i] == null || args[i].getClass().getTypeName().contains("springframework")) {
                    continue;
                }
                if (i > 0) {
                    buffer.append(",");
                }
                buffer.append("arg").append(i + 1).append(":").append(args[i].getClass().getName().substring(args[i].getClass().getName().lastIndexOf(".") + 1)).append("(");
                if (args[i].getClass().isPrimitive() || args[i] instanceof Number || args[i] instanceof Character || args[i] instanceof Boolean || args[i] instanceof String) {
                    buffer.append(args[i].toString());
                } else if (args[i] instanceof Enum) {
                    buffer.append(((Enum) args[i]).name());
                } else {
                    List<Field> fields = new ArrayList<>();
                    Class<?> clazz = args[i].getClass();
                    for (; !(clazz == Object.class); clazz = clazz.getSuperclass()) {
                        fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
                    }
                    int j = 0;
                    for (Field field : fields) {
                        if ("serialVersionUID".contains(field.getName())) {
                            continue;
                        }
                        field.setAccessible(true);
                        Object v = ReflectionUtils.getField(field, args[i]);
                        if (v != null && !v.toString().equals("")) {
                            if (j > 0) {
                                buffer.append(",");
                            }
                            buffer.append(field.getName()).append(":");
                            if (field.getType().equals(Date.class)) {
                                buffer.append(df.format(v));
                            } else {
                                buffer.append(v.toString());
                            }
                            j++;
                        }
                    }
                }
                buffer.append(")");
            }
            return buffer.toString();
        } catch (Exception e) {
            return "parse argument error:" + e.getClass().getName();
        }
    }

    public static String getClientIp() {
        HttpServletRequest request = getRequest();
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("http_client_ip");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        // 如果是多级代理，那么取第一个ip为客户ip
        if (!StringUtils.isEmpty(ip) && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个IP值，第一个不为 unknown 的才为真实IP
            String[] ips = ip.split(",");
            for (String i : ips) {
                i = i.trim();
                if (!StringUtils.isEmpty(i) && !"unknown".equalsIgnoreCase(i)) {
                    ip = i;
                    break;
                }
            }
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip.indexOf(":") > 0) {
            ip = request.getLocalAddr();
        }
        return ip;
    }

    public static HttpServletRequest getRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    }

    public static HttpServletResponse getResponse() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
    }

    public static <T extends Annotation> T getAnnotation(JoinPoint point, Class<T> tClass) {
        return ((MethodSignature) point.getSignature()).getMethod().getAnnotation(tClass);
    }
}
